﻿
Imports std

Namespace internalFunctions
    'parameters, config, var, a config instance
    '            section, any, convert to string, section name
    '            name, any, convert to string, config name
    '            value, pointer<string>/pointer<var>, return
    '            defaultValue, any, convert to string, optional
    '            filter1, string, blank separated, for filter
    '            filter2, ...
    '            filterN
    'return, bool, whether read or not
    Public Class configreader
        Inherits internalFunction

        Public Const filterSeparator As String = character.blank

        Public Class parameters
            Public Const config As String = "config"
            Public Const section As String = "section"
            Public Const name As String = "name"
            Public Const value As String = "value"
            Public Const defaultValue As String = "defaultValue"
            Public Const filterbase As String = "filter"
        End Class

        Public Sub New()
            MyBase.New("config.read")
        End Sub

        Protected Sub New(ByVal name As String)
            MyBase.New(name, Nothing, Nothing, Nothing)
        End Sub

        Protected Overridable Function config(ByVal ctx As context) As configParser
            Dim rtn As configParser = Nothing
            If ctx.findVariable(Of configParser)(parameters.config, rtn) Then
                Return rtn
            Else
                Return Nothing
            End If
        End Function

        Protected Overridable Function filters(ByVal ctx As context) As map(Of String, String)
            Dim rtn As map(Of String, String) = Nothing
            filters = New map(Of String, String)()
            Dim i As Int64
            i = 1
            Dim filter As String = Nothing
            While ctx.findVariableStr(parameters.filterbase + Convert.ToString(i), filter)
                Dim words As vector(Of String) = Nothing
                strsepar(filter, filterSeparator, words, True)
                If words.size() = 2 Then
                    rtn(words(0)) = words(1)
                End If
                i += 1
            End While

            Return rtn
        End Function

        Protected Overridable Function section(ByVal ctx As context) As String
            Return ctx.findVariableStr(parameters.section)
        End Function

        Protected Overridable Overloads Function name(ByVal ctx As context) As String
            Return ctx.findVariableStr(parameters.name)
        End Function

        Protected Overridable Function defaultValue(ByVal ctx As context) As String
            Return ctx.findVariableStr(parameters.defaultValue)
        End Function

        Protected Overridable Overloads Function invokeImpl(ByVal config As configParser, _
                                                            ByVal section As String, _
                                                            ByVal name As String, _
                                                            ByVal defaultValue As String, _
                                                            ByVal filters As map(Of String, String), _
                                                            ByVal ctx As context, _
                                                            ByRef output As bare_variable) As Boolean
            Dim value As bare_variable = Nothing
            If ctx.findVariable(parameters.value, value) Then
                If value.variable().isPointerOfString() Then
                    Dim rtn As Boolean
                    Dim s As String = Nothing
                    rtn = config.trygetparameter(section, name, s, defaultValue, filters) AndAlso _
                          value.setPointerOfString(s)
                    output = New bare_variable(typeDefination.bool, rtn)
                    Return True
                Else
                    raiseError("expect parameter " + parameters.value + " is pointer<string> / pointer<var>.", _
                               errorHandle.errorType.user)
                    Return False
                End If
            Else
                raiseError("expect parameter " + parameters.value, errorHandle.errorType.user)
                Return False
            End If
        End Function

        Protected NotOverridable Overrides Function invoke(ByVal ctx As context, _
                                                           ByRef output As bare_variable) As Boolean
            Dim config As configParser = Nothing
            config = Me.config(ctx)
            If Not config Is Nothing Then
                Return invokeImpl(config, section(ctx), name(ctx), defaultValue(ctx), filters(ctx), ctx, output)
            Else
                raiseError("expect parameter " + parameters.config, errorHandle.errorType.user)
                Return False
            End If
        End Function
    End Class

    'parameters, same as config, only,
    '            value, vector<any>
    '            defaultValue, useless
    'return, same as config
    Public Class configlistreader
        Inherits configreader

        Public Sub New()
            MyBase.New("config.list")
        End Sub

        Protected Sub New(ByVal name As String)
            MyBase.New(name)
        End Sub

        Private Class cbpara
            Public config As configParser = Nothing
            Public section As String = Nothing
            Public name As String = Nothing
            Public filters As map(Of String, String) = Nothing

            Public Sub New(ByVal config As configParser, ByVal section As String, _
                           ByVal name As String, ByVal filters As map(Of String, String))
                Me.config = config
                Me.section = section
                Me.name = name
                Me.filters = filters
            End Sub
        End Class

        Private Shared Function readlist(Of T)(ByVal config As configParser, ByVal section As String, _
                                               ByVal name As String, ByVal filters As map(Of String, String), _
                                               ByVal values As vector(Of T)) As Boolean
            Return config.readlist(section, name, values, filters)
        End Function

        Private Class callback
            Inherits vd_t(Of Boolean)

            Protected Overrides Function cb(Of T)(ByRef i As vector(Of T), ByRef rtn As Boolean, _
                                                  ByVal ParamArray ps() As Object) As Boolean
                Dim para As cbpara = Nothing
                para = paramarray_get(Of cbpara)(0, ps)
                rtn = readlist(para.config, para.section, para.name, para.filters, i)
                Return True
            End Function
        End Class

        Private Shared cb As callback = Nothing

        Shared Sub New()
            cb = New callback()
        End Sub

        Protected Overrides Function invokeImpl(ByVal config As configParser, ByVal section As String, _
                                                ByVal name As String, ByVal defaultValue As String, _
                                                ByVal filters As map(Of String, String), _
                                                ByVal ctx As context, ByRef output As bare_variable) As Boolean
            Dim vv As bare_variable = Nothing
            If ctx.findVariable(parameters.value, vv) Then
                If vv.variable().isType(typeDefination.vector) Then
                    Dim rtn As Boolean
                    If vv.invoke(rtn, _
                                 Nothing, cb, Nothing, Nothing, Nothing, Nothing, _
                                 New cbpara(config, section, name, filters)) Then
                        output = New bare_variable(typeDefination.bool, rtn)
                        Return True
                    Else
                        Return False
                    End If
                Else
                    raiseError("expect parameter " + parameters.value + " is vector<any>.", errorHandle.errorType.user)
                    Return False
                End If
            Else
                raiseError("expect parameter " + parameters.value, errorHandle.errorType.user)
                Return False
            End If
        End Function
    End Class
End Namespace
